﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Linq;
using TT.Logic.Entities;
using TT.Logic;
using TT.Test.Helpers;

namespace TT.Test
{
    [TestClass]
    public class TournamenTest
    {
        [TestMethod]
        public void ShouldGetNextMatchEven()
        {
            using (Fake.FakeDbContext context = new Fake.FakeDbContext())
            {
                var cup = new Logic.Tournament.CupGenerator(context);
                int numberOfPlayers = 4;

                /* R.0 = M.0 = A vs B
                 * R.0 = M.1 = C vs D
                 * 
                 * R.1 = M.0 = --- vs ---
                 */

                var match = new Match();
                match.Round = new Round()
                {
                    RoundNumber = 0
                };
                match.MatchInRoundNumber = 0;

                int? nextMatch = cup.GeNextMatch(match, numberOfPlayers);
                Assert.AreEqual(0, nextMatch);

                match.Round.RoundNumber = 0;
                match.MatchInRoundNumber = 1;
                nextMatch = cup.GeNextMatch(match, numberOfPlayers);
                Assert.AreEqual(0, nextMatch);
                
                //null check
                match.Round.RoundNumber = 1;
                match.MatchInRoundNumber = 0;
                nextMatch = cup.GeNextMatch(match, numberOfPlayers);
                Assert.IsNull(nextMatch);

                match.Round.RoundNumber = 1;
                match.MatchInRoundNumber = 1;
                nextMatch = cup.GeNextMatch(match, numberOfPlayers);
                Assert.IsNull(nextMatch);
            }

        }

        public void ShouldGetNextMatchOdd() {

            using (Fake.FakeDbContext context = new Fake.FakeDbContext())
            {
                var cup = new Logic.Tournament.CupGenerator(context);
                int numberOfPlayers = 5;

                /* R.0 = M.0 = A vs B
                 * 
                 * R.1 = M.0 = C vs D
                 * R.1 = M.1 = E vs ---
                 * 
                 * R.2 = M.0 = --- vs ---
                 */

                var match = new Match();
                match.Round = new Round()
                {
                    RoundNumber = 0
                };

                match.MatchInRoundNumber = 0;                
                
                int? nextMatch = cup.GeNextMatch(match, numberOfPlayers);
                Assert.AreEqual(1, nextMatch);

                match.Round.RoundNumber = 1;
                match.MatchInRoundNumber = 0;
                nextMatch = cup.GeNextMatch(match, numberOfPlayers);
                Assert.AreEqual(0, nextMatch);

                match.Round.RoundNumber = 1;
                match.MatchInRoundNumber = 1;
                nextMatch = cup.GeNextMatch(match, numberOfPlayers);
                Assert.AreEqual(0, nextMatch);
            }
        }

        [TestMethod]        
        public void ShouldGenerateTournamentEven() {
            using (Fake.FakeDbContext context = new Fake.FakeDbContext())
            {
                var players = TestHelpers.GetPlayers(4);

                var cup = new Logic.Tournament.CupGenerator(context);
                var tournament = cup.CreateTournament(players);

                Assert.AreEqual(2, tournament.Rounds.Count);
                Assert.AreEqual(2, tournament.Rounds[0].Matches.Count);
                Assert.AreEqual(1, tournament.Rounds[1].Matches.Count);

                Assert.AreEqual("A", tournament.Rounds[0].Matches[0].HomePlayer1.FirstName);
                Assert.AreEqual("B", tournament.Rounds[0].Matches[0].AwayPlayer1.FirstName);

                Assert.AreEqual("C", tournament.Rounds[0].Matches[1].HomePlayer1.FirstName);
                Assert.AreEqual("D", tournament.Rounds[0].Matches[1].AwayPlayer1.FirstName);

                Assert.IsNull(tournament.Rounds[1].Matches[0].HomePlayer1);
                Assert.IsNull(tournament.Rounds[1].Matches[0].AwayPlayer1);                

            }
        }



        [TestMethod]
        public void ShouldGenerateTournamentOdd()
        {
            using (Fake.FakeDbContext context = new Fake.FakeDbContext())
            {
                var players = TestHelpers.GetPlayers(5);

                var cup = new Logic.Tournament.CupGenerator(context);
                var tournament = cup.CreateTournament(players);

                Assert.AreEqual(3, tournament.Rounds.Count);           
                
                Assert.AreEqual(1, tournament.Rounds[0].Matches.Count);
                Assert.AreEqual(2, tournament.Rounds[1].Matches.Count);
                Assert.AreEqual(1, tournament.Rounds[2].Matches.Count);

                Assert.AreEqual("A", tournament.Rounds[0].Matches[0].HomePlayer1.FirstName);
                Assert.AreEqual("B", tournament.Rounds[0].Matches[0].AwayPlayer1.FirstName);

                Assert.AreEqual("C", tournament.Rounds[1].Matches[0].HomePlayer1.FirstName);
                Assert.AreEqual("D", tournament.Rounds[1].Matches[0].AwayPlayer1.FirstName);

                Assert.AreEqual("E", tournament.Rounds[1].Matches[1].HomePlayer1.FirstName);
                Assert.IsNull(       tournament.Rounds[1].Matches[1].AwayPlayer1);   

                Assert.IsNull(tournament.Rounds[2].Matches[0].HomePlayer1);
                Assert.IsNull(tournament.Rounds[2].Matches[0].AwayPlayer1);   

            }
        }

        [TestMethod]
        public void ShouldProgressPlayerEven()
        {
            using (Fake.FakeDbContext context = new Fake.FakeDbContext())
            {
                var players = TestHelpers.GetPlayers(4);

                var cup = new Logic.Tournament.CupGenerator(context);
                var tournament = cup.CreateTournament(players);

                Assert.AreEqual(2, tournament.Rounds.Count);
                Assert.AreEqual(2, tournament.Rounds[0].Matches.Count);
                Assert.AreEqual(1, tournament.Rounds[1].Matches.Count);

                Assert.AreEqual("A", tournament.Rounds[0].Matches[0].HomePlayer1.FirstName);
                Assert.AreEqual("B", tournament.Rounds[0].Matches[0].AwayPlayer1.FirstName);

                Assert.AreEqual("C", tournament.Rounds[0].Matches[1].HomePlayer1.FirstName);
                Assert.AreEqual("D", tournament.Rounds[0].Matches[1].AwayPlayer1.FirstName);

                Assert.IsNull(tournament.Rounds[1].Matches[0].HomePlayer1);
                Assert.IsNull(tournament.Rounds[1].Matches[0].AwayPlayer1);  

                var match = tournament.Rounds[0].Matches[0];
                var homePlayerName = match.HomePlayer1.FirstName;
                match.HomeScore = 21;
                
                cup.ProgressWinnerToNextRound(match, tournament);

                Assert.AreEqual(2, tournament.Rounds.Count);
                Assert.AreEqual(2, tournament.Rounds[0].Matches.Count);
                Assert.AreEqual(1, tournament.Rounds[1].Matches.Count);

                Assert.AreEqual("A", tournament.Rounds[0].Matches[0].HomePlayer1.FirstName);
                Assert.AreEqual("B", tournament.Rounds[0].Matches[0].AwayPlayer1.FirstName);

                Assert.AreEqual("C", tournament.Rounds[0].Matches[1].HomePlayer1.FirstName);
                Assert.AreEqual("D", tournament.Rounds[0].Matches[1].AwayPlayer1.FirstName);

                //progress
                Assert.AreEqual("A", tournament.Rounds[1].Matches[0].HomePlayer1.FirstName);
                Assert.IsNull(       tournament.Rounds[1].Matches[0].AwayPlayer1);  
                

            }
        }

        [TestMethod]
        public void ShouldProgressPlayerOdd()
        {
            using (Fake.FakeDbContext context = new Fake.FakeDbContext())
            {
                var players = TestHelpers.GetPlayers(5);

                var cup = new Logic.Tournament.CupGenerator(context);
                var tournament = cup.CreateTournament(players);

                Assert.AreEqual(3, tournament.Rounds.Count);

                Assert.AreEqual(1, tournament.Rounds[0].Matches.Count);
                Assert.AreEqual(2, tournament.Rounds[1].Matches.Count);
                Assert.AreEqual(1, tournament.Rounds[2].Matches.Count);

                Assert.AreEqual("A", tournament.Rounds[0].Matches[0].HomePlayer1.FirstName);
                Assert.AreEqual("B", tournament.Rounds[0].Matches[0].AwayPlayer1.FirstName);

                Assert.AreEqual("C", tournament.Rounds[1].Matches[0].HomePlayer1.FirstName);
                Assert.AreEqual("D", tournament.Rounds[1].Matches[0].AwayPlayer1.FirstName);

                Assert.AreEqual("E", tournament.Rounds[1].Matches[1].HomePlayer1.FirstName);
                Assert.IsNull(tournament.Rounds[1].Matches[1].AwayPlayer1);

                Assert.IsNull(tournament.Rounds[2].Matches[0].HomePlayer1);
                Assert.IsNull(tournament.Rounds[2].Matches[0].AwayPlayer1);   

                var match = tournament.Rounds[0].Matches[0];  //A              
                match.HomeScore = 21;

                cup.ProgressWinnerToNextRound(match, tournament);

                Assert.AreEqual(3, tournament.Rounds.Count);

                Assert.AreEqual(1, tournament.Rounds[0].Matches.Count);
                Assert.AreEqual(2, tournament.Rounds[1].Matches.Count);
                Assert.AreEqual(1, tournament.Rounds[2].Matches.Count);

                Assert.AreEqual("A", tournament.Rounds[0].Matches[0].HomePlayer1.FirstName);
                Assert.AreEqual("B", tournament.Rounds[0].Matches[0].AwayPlayer1.FirstName);

                Assert.AreEqual("C", tournament.Rounds[1].Matches[0].HomePlayer1.FirstName);
                Assert.AreEqual("D", tournament.Rounds[1].Matches[0].AwayPlayer1.FirstName);

                Assert.AreEqual("E", tournament.Rounds[1].Matches[1].HomePlayer1.FirstName);
                //progress
                Assert.AreEqual("A", tournament.Rounds[1].Matches[1].AwayPlayer1.FirstName);

                Assert.IsNull(tournament.Rounds[2].Matches[0].HomePlayer1);
                Assert.IsNull(tournament.Rounds[2].Matches[0].AwayPlayer1);

                match = tournament.Rounds[1].Matches[0];    //C            
                match.HomeScore = 21;
                cup.ProgressWinnerToNextRound(match, tournament);

                match = tournament.Rounds[1].Matches[1];    //A       
                match.AwayScore = 21;
                cup.ProgressWinnerToNextRound(match, tournament);

                Assert.AreEqual(3, tournament.Rounds.Count);

                Assert.AreEqual(1, tournament.Rounds[0].Matches.Count);
                Assert.AreEqual(2, tournament.Rounds[1].Matches.Count);
                Assert.AreEqual(1, tournament.Rounds[2].Matches.Count);

                Assert.AreEqual("A", tournament.Rounds[0].Matches[0].HomePlayer1.FirstName);
                Assert.AreEqual("B", tournament.Rounds[0].Matches[0].AwayPlayer1.FirstName);

                Assert.AreEqual("C", tournament.Rounds[1].Matches[0].HomePlayer1.FirstName);
                Assert.AreEqual("D", tournament.Rounds[1].Matches[0].AwayPlayer1.FirstName);

                Assert.AreEqual("E", tournament.Rounds[1].Matches[1].HomePlayer1.FirstName);                
                Assert.AreEqual("A", tournament.Rounds[1].Matches[1].AwayPlayer1.FirstName);
                //progress
                Assert.AreEqual("C", tournament.Rounds[2].Matches[0].HomePlayer1.FirstName);
                Assert.AreEqual("A", tournament.Rounds[2].Matches[0].AwayPlayer1.FirstName);


            }
        }


        [TestMethod]
        public void ShouldGetByes()
        {
            using (Fake.FakeDbContext context = new Fake.FakeDbContext())
            {
                var cup = new Logic.Tournament.CupGenerator(context);
                Assert.AreEqual(0, cup.GetByes(4));
                Assert.AreEqual(3, cup.GetByes(5));
                Assert.AreEqual(2, cup.GetByes(6));
                Assert.AreEqual(1, cup.GetByes(7));
            }
        }
     
    }
}
